home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / app / magnify.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-09  |  11.1 KB  |  468 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdlib.h>
  22.  
  23. #include <gtk/gtk.h>
  24. #include <gdk/gdkkeysyms.h>
  25.  
  26. #include "apptypes.h"
  27.  
  28. #include "appenv.h"
  29. #include "cursorutil.h"
  30. #include "draw_core.h"
  31. #include "gdisplay.h"
  32. #include "gimprc.h"
  33. #include "gimpui.h"
  34. #include "info_window.h"
  35. #include "magnify.h"
  36. #include "scale.h"
  37.  
  38. #include "config.h"
  39. #include "libgimp/gimpintl.h"
  40.  
  41. /*  the magnify structures  */
  42.  
  43. typedef struct _Magnify Magnify;
  44.  
  45. struct _Magnify
  46. {
  47.   DrawCore *core;       /*  Core select object          */
  48.  
  49.   gint      x, y;       /*  upper left hand coordinate  */
  50.   gint      w, h;       /*  width and height            */
  51.  
  52.   gint      op;         /*  magnify operation           */
  53. };
  54.  
  55. typedef struct _MagnifyOptions MagnifyOptions;
  56.  
  57. struct _MagnifyOptions
  58. {
  59.   ToolOptions  tool_options;
  60.  
  61.   /* gint      allow_resize_windows; (from gimprc) */
  62.   gint         allow_resize_d;
  63.   GtkWidget   *allow_resize_w;
  64.  
  65.   ZoomType     type;
  66.   ZoomType     type_d;
  67.   GtkWidget   *type_w[2];
  68. };
  69.  
  70.  
  71. /*  the magnify tool options  */
  72. static MagnifyOptions *magnify_options = NULL;
  73.  
  74.  
  75. /*  magnify action functions  */
  76. static void   magnify_button_press      (Tool *, GdkEventButton *, gpointer);
  77. static void   magnify_button_release    (Tool *, GdkEventButton *, gpointer);
  78. static void   magnify_motion            (Tool *, GdkEventMotion *, gpointer);
  79. static void   magnify_modifier_update   (Tool *, GdkEventKey *,    gpointer);
  80. static void   magnify_cursor_update     (Tool *, GdkEventMotion *, gpointer);
  81. static void   magnify_control           (Tool *, ToolAction,       gpointer);
  82.  
  83. /*  magnify utility functions  */
  84. static void   zoom_in                   (gint *src,
  85.                      gint *dest,
  86.                      gint  scale);
  87. static void   zoom_out                  (gint *src,
  88.                      gint *dest,
  89.                      gint  scale);
  90.  
  91.  
  92. /*  magnify tool options functions  */
  93.  
  94. static void
  95. magnify_options_reset (void)
  96. {
  97.   MagnifyOptions *options = magnify_options;
  98.  
  99.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->allow_resize_w),
  100.                 options->allow_resize_d);
  101.  
  102.   gtk_toggle_button_set_active
  103.     (GTK_TOGGLE_BUTTON (options->type_w[options->type_d]), TRUE);
  104. }
  105.  
  106. static MagnifyOptions *
  107. magnify_options_new (void)
  108. {
  109.   MagnifyOptions *options;
  110.  
  111.   GtkWidget *vbox;
  112.   GtkWidget *frame;
  113.  
  114.   /*  the new magnify tool options structure  */
  115.   options = g_new (MagnifyOptions, 1);
  116.   tool_options_init ((ToolOptions *) options,
  117.              _("Magnify Tool"),
  118.              magnify_options_reset);
  119.   options->allow_resize_d = allow_resize_windows;
  120.   options->type_d         = options->type = ZOOMIN;
  121.  
  122.   /*  the main vbox  */
  123.   vbox = options->tool_options.main_vbox;
  124.  
  125.   /*  the allow_resize toggle button  */
  126.   options->allow_resize_w =
  127.     gtk_check_button_new_with_label (_("Allow Window Resizing"));
  128.   gtk_signal_connect (GTK_OBJECT (options->allow_resize_w), "toggled",
  129.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  130.               &allow_resize_windows);
  131.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->allow_resize_w),
  132.                 allow_resize_windows);
  133.   gtk_box_pack_start (GTK_BOX (vbox), options->allow_resize_w, FALSE, FALSE, 0);
  134.   gtk_widget_show (options->allow_resize_w);
  135.  
  136.   /*  tool toggle  */
  137.   frame =
  138.     gimp_radio_group_new2 (TRUE, _("Tool Toggle"),
  139.                            gimp_radio_button_update,
  140.                            &options->type, (gpointer) options->type,
  141.  
  142.                            _("Zoom in"), (gpointer) ZOOMIN,
  143.                            &options->type_w[0],
  144.                            _("Zoom out"), (gpointer) ZOOMOUT,
  145.                            &options->type_w[1],
  146.  
  147.                            NULL);
  148.  
  149.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  150.   gtk_widget_show (frame);
  151.  
  152.   return options;
  153. }
  154.  
  155. /*  magnify utility functions  */
  156.  
  157. static void
  158. zoom_in (gint *src,
  159.      gint *dest,
  160.      gint  scale)
  161. {
  162.   while (scale--)
  163.     {
  164.       if (*src > 1)
  165.     (*src)--;
  166.       else
  167.     if (*dest < 0x10)
  168.       (*dest)++;
  169.     }
  170. }
  171.  
  172.  
  173. static void
  174. zoom_out (gint *src,
  175.       gint *dest,
  176.       gint  scale)
  177. {
  178.   while (scale--)
  179.     {
  180.       if (*dest > 1)
  181.     (*dest)--;
  182.       else
  183.     if (*src < 0x10)
  184.       (*src)++;
  185.     }
  186. }
  187.  
  188.  
  189. /*  magnify action functions  */
  190.  
  191. static void
  192. magnify_button_press (Tool           *tool,
  193.               GdkEventButton *bevent,
  194.               gpointer        gdisp_ptr)
  195. {
  196.   GDisplay *gdisp;
  197.   Magnify *magnify;
  198.   gint x, y;
  199.  
  200.   gdisp = (GDisplay *) gdisp_ptr;
  201.   magnify = (Magnify *) tool->private;
  202.  
  203.   gdisplay_untransform_coords (gdisp, 
  204.                                bevent->x, bevent->y, &x, &y, TRUE, FALSE);
  205.  
  206.   magnify->x = x;
  207.   magnify->y = y;
  208.   magnify->w = 0;
  209.   magnify->h = 0;
  210.  
  211.   gdk_pointer_grab (gdisp->canvas->window, FALSE,
  212.             GDK_POINTER_MOTION_HINT_MASK |
  213.             GDK_BUTTON1_MOTION_MASK |
  214.             GDK_BUTTON_RELEASE_MASK,
  215.             NULL, NULL, bevent->time);
  216.  
  217.   tool->state = ACTIVE;
  218.   tool->gdisp_ptr = gdisp_ptr;
  219.  
  220.   draw_core_start (magnify->core,
  221.            gdisp->canvas->window,
  222.            tool);
  223. }
  224.  
  225.  
  226. static void
  227. magnify_button_release (Tool           *tool,
  228.             GdkEventButton *bevent,
  229.             gpointer        gdisp_ptr)
  230. {
  231.   Magnify *magnify;
  232.   GDisplay *gdisp;
  233.   gint win_width, win_height;
  234.   gint width, height;
  235.   gint scalesrc, scaledest;
  236.   gint scale;
  237.   gint x1, y1, x2, y2, w, h;
  238.  
  239.   gdisp = (GDisplay *) gdisp_ptr;
  240.   magnify = (Magnify *) tool->private;
  241.  
  242.   gdk_pointer_ungrab (bevent->time);
  243.   gdk_flush ();
  244.  
  245.   draw_core_stop (magnify->core, tool);
  246.   tool->state = INACTIVE;
  247.  
  248.   /*  First take care of the case where the user "cancels" the action  */
  249.   if (! (bevent->state & GDK_BUTTON3_MASK))
  250.     {
  251.       x1 = (magnify->w < 0) ? magnify->x + magnify->w : magnify->x;
  252.       y1 = (magnify->h < 0) ? magnify->y + magnify->h : magnify->y;
  253.       w = (magnify->w < 0) ? -magnify->w : magnify->w;
  254.       h = (magnify->h < 0) ? -magnify->h : magnify->h;
  255.       x2 = x1 + w;
  256.       y2 = y1 + h;
  257.  
  258.       /* these change the user zoom level, so should not be changed to
  259.        * the resolution-aware scale macros -- austin */
  260.       scalesrc = SCALESRC (gdisp);
  261.       scaledest = SCALEDEST (gdisp);
  262.  
  263.       win_width = gdisp->disp_width;
  264.       win_height = gdisp->disp_height;
  265.       width = (win_width * scalesrc) / scaledest;
  266.       height = (win_height * scalesrc) / scaledest;
  267.  
  268.       if (!w || !h)
  269.     scale = 1;
  270.       else
  271.     scale = MIN ((width / w), (height / h));
  272.  
  273.       magnify->op = magnify_options->type;
  274.  
  275.       switch (magnify->op)
  276.     {
  277.     case ZOOMIN:
  278.       zoom_in (&scalesrc, &scaledest, scale);
  279.       break;
  280.     case ZOOMOUT:
  281.       zoom_out (&scalesrc, &scaledest, scale);
  282.       break;
  283.     }
  284.  
  285.       gdisp->scale = (scaledest << 8) + scalesrc;
  286.       gdisp->offset_x = (scaledest * ((x1 + x2) / 2)) / scalesrc -
  287.     (win_width / 2);
  288.       gdisp->offset_y = (scaledest * ((y1 + y2) / 2)) / scalesrc -
  289.     (win_height / 2);
  290.  
  291.       /*  resize the image  */
  292.       resize_display (gdisp, allow_resize_windows, TRUE);
  293.     }
  294. }
  295.  
  296. static void
  297. magnify_motion (Tool           *tool,
  298.         GdkEventMotion *mevent,
  299.         gpointer        gdisp_ptr)
  300. {
  301.   Magnify *magnify;
  302.   GDisplay *gdisp;
  303.   gint x, y;
  304.  
  305.   if (tool->state != ACTIVE)
  306.     return;
  307.  
  308.   gdisp = (GDisplay *) gdisp_ptr;
  309.   magnify = (Magnify *) tool->private;
  310.  
  311.   draw_core_pause (magnify->core, tool);
  312.  
  313.   gdisplay_untransform_coords (gdisp, 
  314.                                mevent->x, mevent->y, &x, &y, TRUE, FALSE);
  315.   magnify->w = (x - magnify->x);
  316.   magnify->h = (y - magnify->y);
  317.  
  318.   draw_core_resume (magnify->core, tool);
  319. }
  320.  
  321.  
  322. static void
  323. magnify_modifier_update (Tool        *tool,
  324.              GdkEventKey *kevent,
  325.              gpointer     gdisp_ptr)
  326. {
  327.   switch (kevent->keyval)
  328.     {
  329.     case GDK_Alt_L: case GDK_Alt_R:
  330.       break;
  331.     case GDK_Shift_L: case GDK_Shift_R:
  332.       break;
  333.     case GDK_Control_L: case GDK_Control_R:
  334.       if (magnify_options->type == ZOOMIN)
  335.         gtk_toggle_button_set_active
  336.       (GTK_TOGGLE_BUTTON (magnify_options->type_w[ZOOMOUT]), TRUE);
  337.       else
  338.         gtk_toggle_button_set_active
  339.       (GTK_TOGGLE_BUTTON (magnify_options->type_w[ZOOMIN]), TRUE);
  340.       break;
  341.     }
  342. }
  343.   
  344. static void
  345. magnify_cursor_update (Tool           *tool,
  346.                GdkEventMotion *mevent,
  347.                gpointer        gdisp_ptr)
  348. {
  349.   GDisplay *gdisp;
  350.  
  351.   gdisp = (GDisplay *) gdisp_ptr;
  352.  
  353.   if (magnify_options->type == ZOOMIN)
  354.     {
  355.       gdisplay_install_tool_cursor (gdisp, GIMP_ZOOM_CURSOR,
  356.                     MAGNIFY,
  357.                     CURSOR_MODIFIER_PLUS,
  358.                     FALSE);
  359.     }
  360.   else
  361.     {
  362.       gdisplay_install_tool_cursor (gdisp, GIMP_ZOOM_CURSOR,
  363.                     MAGNIFY,
  364.                     CURSOR_MODIFIER_MINUS,
  365.                     FALSE);
  366.    }
  367. }
  368.  
  369.  
  370. void
  371. magnify_draw (Tool *tool)
  372. {
  373.   GDisplay *gdisp;
  374.   Magnify *magnify;
  375.   gint x1, y1, x2, y2;
  376.  
  377.   gdisp = (GDisplay *) tool->gdisp_ptr;
  378.   magnify = (Magnify *) tool->private;
  379.  
  380.   x1 = MIN (magnify->x, magnify->x + magnify->w);
  381.   y1 = MIN (magnify->y, magnify->y + magnify->h);
  382.   x2 = MAX (magnify->x, magnify->x + magnify->w);
  383.   y2 = MAX (magnify->y, magnify->y + magnify->h);
  384.  
  385.   gdisplay_transform_coords (gdisp, x1, y1, &x1, &y1, FALSE);
  386.   gdisplay_transform_coords (gdisp, x2, y2, &x2, &y2, FALSE);
  387.  
  388.   gdk_draw_rectangle (magnify->core->win, magnify->core->gc, FALSE,
  389.               x1, y1, (x2 - x1), (y2 - y1));
  390. }
  391.  
  392.  
  393. static void
  394. magnify_control (Tool       *tool,
  395.          ToolAction  action,
  396.          gpointer    gdisp_ptr)
  397. {
  398.   Magnify *magnify;
  399.  
  400.   magnify = (Magnify *) tool->private;
  401.  
  402.   switch (action)
  403.     {
  404.     case PAUSE:
  405.       draw_core_pause (magnify->core, tool);
  406.       break;
  407.  
  408.     case RESUME:
  409.       draw_core_resume (magnify->core, tool);
  410.       break;
  411.  
  412.     case HALT:
  413.       draw_core_stop (magnify->core, tool);
  414.       break;
  415.  
  416.     default:
  417.       break;
  418.     }
  419. }
  420.  
  421.  
  422. Tool *
  423. tools_new_magnify (void)
  424. {
  425.   Tool *tool;
  426.   Magnify *private;
  427.  
  428.   /*  The tool options  */
  429.   if (! magnify_options)
  430.     {
  431.       magnify_options = magnify_options_new ();
  432.       tools_register (MAGNIFY, (ToolOptions *) magnify_options);
  433.     }
  434.  
  435.   tool = tools_new_tool (MAGNIFY);
  436.   private = g_new0 (Magnify, 1);
  437.  
  438.   private->core = draw_core_new (magnify_draw);
  439.   private->x = private->y = 0;
  440.   private->w = private->h = 0;
  441.  
  442.   tool->scroll_lock  = TRUE;   /*  Disallow scrolling  */
  443.   tool->auto_snap_to = FALSE;  /*  Don't snap to guides  */
  444.  
  445.   tool->private = (void *) private;
  446.  
  447.   tool->button_press_func   = magnify_button_press;
  448.   tool->button_release_func = magnify_button_release;
  449.   tool->motion_func         = magnify_motion;
  450.   tool->modifier_key_func   = magnify_modifier_update;
  451.   tool->cursor_update_func  = magnify_cursor_update;
  452.   tool->control_func        = magnify_control;
  453.  
  454.   return tool;
  455. }
  456.  
  457.  
  458. void
  459. tools_free_magnify (Tool *tool)
  460. {
  461.   Magnify *magnify;
  462.  
  463.   magnify = (Magnify *) tool->private;
  464.  
  465.   draw_core_free (magnify->core);
  466.   g_free (magnify);
  467. }
  468.